package com.wzdigit.wms.raw.service.inv;

import com.alibaba.fastjson.JSON;
import com.wzdigit.framework.Shift;
import com.wzdigit.wms.basic.client.request.inv.SearchGoodsSplitRequest;
import com.wzdigit.wms.basic.client.request.inv.SubmitGoodsSplitRequest;
import com.wzdigit.wms.basic.client.response.inv.GoodsSplitInfoResponse;
import com.wzdigit.wms.basic.client.response.inv.GoodsSplitSubmitResponse;
import com.wzdigit.wms.basic.domain.inventory.Goods;
import com.wzdigit.wms.basic.domain.inventory.GoodsLog;
import com.wzdigit.wms.basic.domain.inventory.GoodsVersion;
import com.wzdigit.wms.basic.enums.GoodsStatusEnum;
import com.wzdigit.wms.basic.enums.IsHoldEnum;
import com.wzdigit.wms.basic.enums.OpCodeEnum;
import com.wzdigit.wms.basic.enums.QaStatusEnum;
import com.wzdigit.wms.basic.enums.log.GoodsLogEnum;
import com.wzdigit.wms.basic.mapper.core.inventory.GoodsLogMapper;
import com.wzdigit.wms.basic.mapper.core.inventory.GoodsMapper;
import com.wzdigit.wms.basic.mapper.core.inventory.manager.GoodsSplitMapper;
import com.wzdigit.wms.basic.service.code.GoodsSerialCoreService;
import com.wzdigit.wms.basic.service.code.GoodsVersionService;
import com.wzdigit.wms.basic.util.HttpSessionUtil;
import com.wzdigit.wms.basic.util.common.SeparatorString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 
 * 物料拆分-服务类
 * 
 * @author Administrator
 *
 */
@Service
@Slf4j
public class GoodsSplitService {

    @Autowired
    private GoodsSplitMapper goodsSplitMapper;

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private GoodsLogMapper goodsLogMapper;
    
    @Autowired
	private GoodsVersionService goodsVersionService;
    
    @Autowired
	private GoodsSerialCoreService goodsSerialCoreService;
    
    /**
     * 扫描条码
     * 
     * @param dto
     * @return
     */
    public GoodsSplitInfoResponse scanInfo(SearchGoodsSplitRequest dto) {
    	GoodsSplitInfoResponse goods = check(dto.getGoodsSn());
        return goods;
    }

    /**
     * 物料拆分提交
     * 
     * @param dto
     * @param servletRequest
     * @return
     * @throws InterruptedException 
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public List<GoodsSplitSubmitResponse> submit(SubmitGoodsSplitRequest dto, HttpServletRequest servletRequest) throws InterruptedException {
    	GoodsSplitInfoResponse goods = check(dto.getGoodsSn());
        // 拆分数量不能为0
        if(dto.getSplitQty().signum() == 0) {
			Shift.fatal(String.format("拆分数量不能为0"));
		}
        // 拆分数量不能超过物料数量
        if(dto.getSplitQty().compareTo(goods.getQty()) == 1) {
			Shift.fatal(String.format("拆分数量不能超过物料数量"));
		}

        
        // 操作人、当前系统时间
        String loginName = HttpSessionUtil.getLoginName(servletRequest);
        Date date = new Date();
        
        // 新条码
     	String newGoodsSn = goodsSerialCoreService.generateGoodsSn(goods.getGoodsSn());
     		
    	// 拆分数
        BigDecimal splitQty = dto.getSplitQty();
        
        // 源条码
        GoodsVersion sourceGoods = goodsVersionService.selectBySn(goods.getGoodsSn());
        sourceGoods.setVersion(goods.getVersion());
        
        // 新条码
        Goods goodsNew = new Goods();
        BeanUtils.copyProperties(sourceGoods, goodsNew);
        goodsNew.setGoodsId(null);
        goodsNew.setPkgId(null);
        goodsNew.setModifyTime(null);
        goodsNew.setModifyUser(null);

        goodsNew.setCreateTime(date);
        goodsNew.setCreateUser(loginName);
        goodsNew.setGoodsSn(newGoodsSn);

        goodsNew.setQty(splitQty);
        goodsNew.setIsOriginalPackage(0);
        goodsNew.setSourceGoodsId(sourceGoods.getGoodsId());
        goodsNew.setComments(String.format("拆分自[%s]，拆分数量[%s]", sourceGoods.getGoodsSn(), splitQty.toString()));
        goodsMapper.insert(goodsNew);

        // 新条码LOG
        GoodsLog newGoodsLog = new GoodsLog();
        newGoodsLog.setGoodsSn(goodsNew.getGoodsSn());
        newGoodsLog.setOperator(loginName);
        newGoodsLog.setCreateUser(loginName);
        newGoodsLog.setCreateTime(date);
        newGoodsLog.setOperator(loginName);
        newGoodsLog.setOpCode(GoodsLogEnum.CREATE.getCode());
        newGoodsLog.setReason(String.format("源SN[%s]拆分建档", sourceGoods.getGoodsSn()));
        newGoodsLog.setUpdateContent(JSON.toJSONString(goodsNew));
        goodsLogMapper.insert(newGoodsLog);

        // 原条码
        String oldSourceGoodsLog = JSON.toJSONString(sourceGoods); 		// 原先的json
        sourceGoods.setQty(splitQty.negate());							// qty更新的阀值【-】
		sourceGoods.setModifyTime(date);
		sourceGoods.setModifyUser(loginName);
		goodsVersionService.updateQtyById(sourceGoods);
		String newSourceGoodsLog = JSON.toJSONString(sourceGoods); 		// 更新后的json
		
        GoodsLog goodsLogSource = new GoodsLog();
        goodsLogSource.setGoodsSn(sourceGoods.getGoodsSn());
        goodsLogSource.setOperator(loginName);
        goodsLogSource.setCreateUser(loginName);
        goodsLogSource.setCreateTime(date);
        goodsLogSource.setOperator(loginName);
        goodsLogSource.setOpCode(OpCodeEnum.SPLIT.getCode());
        goodsLogSource.setReason(OpCodeEnum.SPLIT.getEnumName());
        goodsLogSource.setUpdateContent("未更新:" + oldSourceGoodsLog + ",更新后:" + newSourceGoodsLog);
        goodsLogMapper.insert(goodsLogSource);

        // 响应值
        List<GoodsSplitSubmitResponse> list = new ArrayList<>(1);
        GoodsSplitSubmitResponse response = new GoodsSplitSubmitResponse();
        response.setGoodsId(goodsNew.getGoodsId());
        response.setGoodsSn(goodsNew.getGoodsSn());
        response.setQty(goodsNew.getQty());
        response.setSnType(goodsNew.getSnType());
        response.setCreateTime(goodsNew.getCreateTime());
        list.add(response);
        return list;
    }
    
    private GoodsSplitInfoResponse check(String sn) {
    	GoodsSplitInfoResponse goods = goodsSplitMapper.selectInfoBySn(sn);
        // 【检验1】条码不存在
        if(goods == null) {
            Shift.fatal(String.format("SN[%s]条码不存在", sn));
        }

        
        // 【检验2】物料数量不能为0
        if(goods.getQty().signum() == 0) {
			Shift.fatal(String.format("SN[%s]数量为0，不能进行物料拆分", goods.getGoodsSn()));
		}
        
        // 【检验3】待入库/已拣选/已出库/在途/已报废
        if(Objects.equals(goods.getStatus(), GoodsStatusEnum.WAIT_IN.code) ||
                Objects.equals(goods.getStatus(), GoodsStatusEnum.HAS_DOWN.code) ||
                Objects.equals(goods.getStatus(), GoodsStatusEnum.HAS_CHUKU.code) ||
                Objects.equals(goods.getStatus(), GoodsStatusEnum.OUT_ONLOAD.code) ||
                Objects.equals(goods.getStatus(), GoodsStatusEnum.SCRAP.code)) {
            Shift.fatal(String.format("SN[%s]状态为[%s]不可进行拆分", goods.getGoodsSn(), GoodsStatusEnum.getEnumByCode(goods.getStatus()).enumName));
        }
        
        // 【检验4】冻结状态下的SN不能进行料号拆分
        if (Objects.equals(goods.getIsHold(), IsHoldEnum.Yes.code)) {
            Shift.fatal(String.format("SN[%s]被冻结不可进行拆分", goods.getGoodsSn()));
        }
        
        // 【检验5】物料品质状态必须为“合格”
        if (!Objects.equals(goods.getQaStatus(), QaStatusEnum.OK.code)) {
            Shift.fatal(String.format("SN[%s]品质状态为[%s]，不能进行拆分", goods.getGoodsSn(), QaStatusEnum.getEnumByCode(goods.getQaStatus()).enumName));
        }
        return goods;
	}
}
